package thumb

import (
	"bytes"
	"encoding/json"
	"fmt"
	"github.com/pkg/errors"
	"go.uber.org/zap"
	"myCloud/constant"
	"myCloud/dbopr"
	"myCloud/logsvr"
	"nanomsg.org/go-mangos"
	"nanomsg.org/go-mangos/protocol/sub"
	"nanomsg.org/go-mangos/transport/inproc"
	"strings"
)

var (
	logger = logsvr.GetLogger("thumb")
)

func SvrInit(thumbPath, mqPath string) {
	// 首先应该打开数据库
	err := openBoltThumbStorage(thumbPath)
	if err != nil {
		logger.Errorw("open thumb storage failed, it's ready running?")
		return
	}

	sock, err := sub.NewSocket()
	if err != nil {
		logger.Errorw("new publish socket failed.", zap.Error(err))
		return
	}

	//sock.AddTransport(ipc.NewTransport())
	//sock.AddTransport(tcp.NewTransport())
	sock.AddTransport(inproc.NewTransport())

	err = sock.Dial(mqPath)
	if err != nil {
		panic("can't dial on sub socket")
	}
	logger.Debug("connected to mq service")
	// Empty byte array effectively subscribes to everything
	err = sock.SetOption(mangos.OptionSubscribe, []byte(""))
	if err != nil {
		panic("cannot subscribe")
	}

	for {
		msg, err := sock.Recv()
		if err != nil {
			panic("Cannot recv")
		}
		fmt.Printf("CLIENT(%s): RECEIVED %s\n", "client0", string(msg))
		handleMessage(msg)
	}
}

func deserializeNanoMsg(body []byte) (string, []byte, error) {
	pos := bytes.IndexByte(body, 0)
	if pos == -1 {
		return "", nil, errors.New("message cannot include separate char.")
	}

	topic := string(body[:pos])
	return topic, body[pos+1:], nil
}

func handleMessage(msg []byte) {
	topic, body, err := deserializeNanoMsg(msg)
	if err != nil {
		logger.Error("deserialize pipe message failed")
		return
	}

	switch topic {
	case constant.NotifyFileUploadFinished:
		handleFileUploadFinished(body)
		break
	default:
		handleUnknownTopic(topic, body)
		break
	}

}

func handleFileUploadFinished(body []byte) {
	logger.Info("recv from pipe", zap.String("msg", string(body)))
	var eventInfo = make(map[string]int)
	err := json.Unmarshal(body, &eventInfo)
	if err != nil {
		logger.Warnw("json unmarshal failed")
		return
	}

	evtID, ok := eventInfo["event_id"]
	if !ok {
		logger.Warnw("cannot found event_id field")
		return
	}

	p := dbopr.NewFileProvider()
	fileInfo, notFound, err := p.GetByID(evtID)
	if err != nil {
		logger.Warnw("found special file info failed", zap.Int("file", evtID))
		return
	}
	if notFound {
		logger.Warnw("cannot found special file info", zap.Int("file", evtID))
		return
	}

	if !strings.HasPrefix(fileInfo.CType, "image") {
		logger.Warnw("file not a picture, ignored", zap.Int("file", evtID))
		return
	}

	// 用户上传的相册图片，应
	// 构建缩略图
	err = generateThumb(fileInfo)
	if err != nil {
		logger.Warnw("picture thumbnail failed", zap.Int("file", evtID), zap.Error(err))
		return
	}

	// 更新相册缩略图，指向最新？
	err = addAlbumInfo(fileInfo)
	if err != nil {
		logger.Warnw("album thumbnail failed", zap.Int("file", evtID), zap.Error(err))
		return
	}
}

func handleUnknownTopic(s string, _ []byte) {
	println("unknown topic")
	println(s)
}
